package org.banxico.ds.sisal.dao;

import java.net.URL;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.Collections;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.banxico.ds.sisal.db.ConnectionFactory;
import org.banxico.ds.sisal.entities.Grupo;
import org.banxico.ds.sisal.entities.Software;
import org.banxico.ds.sisal.entities.Vulnerabilidad;
import org.banxico.ds.sisal.entities.VulnerabilidadReferencia;
import org.banxico.ds.sisal.parser.VulnerabilityParser;
import org.banxico.ds.sisal.parser.entidades.CVE;
import org.banxico.ds.sisal.parser.entidades.CVEReference;
import org.banxico.ds.sisal.parser.entidades.VulnSoftware;
import org.banxico.ds.sisal.scanner.Result;
import org.banxico.ds.sisal.scanner.ScannerBean;

/**
 * Clase que se encarga de manejar el acceso a datos relacionados con la entidad
 * Vulnerabilidad
 *
 * @author t41507
 * @version 01.09.2014
 */
public class VulnerabilityDAO {

    /**
     * Atributo LOGGER
     */
    private static final Logger LOG = Logger.getLogger(VulnerabilityDAO.class.getName());
    /**
     * Atributos de Conexión
     */
    private Connection connection;
    private PreparedStatement pstmt;
    private ResultSet rs;
    //TODO: Eliminar este atributo
    Statement stmt;
    /**
     * Atributos del DAO
     */
    private VulnerabilityParser mCVEParser;
    private int cantidadRecientes;
    private int cantidadArchivo;
    private List<CVE> listaRecientes;
    private List<CVE> listaArchivo;
    private List<String> nombres;
    /**
     * Consultas SQL
     */
    private static final String getURLQuery = "SELECT url FROM FuenteApp WHERE idFuenteApp = ?";
    private static final String sqlInsertarVulnerabilidad = "INSERT INTO Vulnerabilidad(idVulnerabilidad, severidad, fecha_publicacion, "
            + "fecha_modificacion, descripcion, calificacion_cvss, vector_cvss) VALUES (?, ?, ?, ?, ?, ?, ?)";
    private static final String sqlInsertVulnReference = "INSERT INTO Vulnerabilidad_Referencia(idVulnerabilidad, fuente, url) VALUES (?, ?, ?);";
    private static final String sqlInsertVulnSW = "INSERT INTO Vulnerabilidad_Software(idVulnerabilidad, idSoftware) VALUES (?, ?);";
    private static final String sqlActualizarVulnerabilidad = "UPDATE Vulnerabilidad"
            + " SET severidad = ?, fecha_publicacion = ?, fecha_modificacion = ?, descripcion = ?, calificacion_cvss = ?, vector_cvss = ? "
            + "WHERE idVulnerabilidad = ?";
    private static final String sqlEliminarVulnerabilidad = "DELETE FROM Vulnerabilidad WHERE idVulnerabilidad = ?";
    private static final String sqlSeleccionarVulnerabilidades = "SELECT * FROM Vulnerabilidad";
    private static final String sqlBuscarExistenciaVulnerabilidad = "SELECT * FROM Vulnerabilidad v WHERE v.idVulnerabilidad LIKE ?";
    private static final String sqlObtenerVulnerabilidadesRecientes = "SELECT * FROM Vulnerabilidad v, Vulnerabilidad_Software x, Software s "
            + "WHERE v.idVulnerabilidad = x.idVulnerabilidad and x.idSoftware = s.idSoftware "
            + "AND v.fecha_publicacion > GETDATE() - 8 "
            + "ORDER BY v.fecha_publicacion DESC;";
    private static final String sqlObtenerSoftwareDeVulnerabilidad = "SELECT * FROM Software s, Vulnerabilidad_Software x "
            + "WHERE s.idSoftware = x.idSoftware AND x.idVulnerabilidad = ?";
    private static final String sqlObtenerGruposConSoftware = "SELECT g.idGrupo, g.nombre, g.categoria "
            + "FROM Software s, Grupo_Software x, Grupo g "
            + "WHERE s.idSoftware = x.idSoftware AND x.idGrupo = g.idGrupo AND s.idSoftware = ?";
    private static final String sqlObtenerVulnerabilidadPorNombre = "SELECT * FROM Vulnerabilidad v WHERE v.idVulnerabilidad = ?";
    private static final String sqlObtenerReferenciasPorNombre = "SELECT x.idVulnerabilidad, x.idReferencia, x.fuente, x.url "
            + "FROM Vulnerabilidad v, Vulnerabilidad_Referencia x "
            + "WHERE v.idVulnerabilidad = x.idVulnerabilidad "
            + "AND v.idVulnerabilidad = ?";
    private static final String sqlObtenerSoftwareVulnerablePorNombre = "SELECT s.idSoftware, s.fabricante, s.nombre, s.version, s.tipo, s.end_of_life "
            + "FROM Software s, Vulnerabilidad_Software x "
            + "WHERE s.idSoftware = x.idSoftware AND x.idVulnerabilidad = ?";
    private static final String sqlObtenerGruposPorVulnerabilidad = "SELECT DISTINCT g.idGrupo, g.nombre, g.categoria "
            + "FROM Vulnerabilidad_Software x, Software s, Grupo_Software y, Grupo g "
            + "WHERE x.idSoftware = s.idSoftware AND s.idSoftware = y.idSoftware AND y.idGrupo = g.idGrupo AND x.idVulnerabilidad = ?";
    private static final String sqlObtenerGravedadVulnerabilidades = "SELECT DISTINCT "
            + "(SELECT COUNT(*) FROM Vulnerabilidad v WHERE v.severidad LIKE '%alta%') AS ALTAS, "
            + "(SELECT COUNT(*) FROM Vulnerabilidad v WHERE v.severidad LIKE '%media%') AS MEDIAS, "
            + "(SELECT COUNT(*) FROM Vulnerabilidad v WHERE v.severidad LIKE '%baja%') AS BAJAS "
            + "FROM Vulnerabilidad v;";
    private static final String sqlObtenerVulnerabilidadesporFabricante = "SELECT DISTINCT s.fabricante, COUNT(DISTINCT v.idVulnerabilidad) AS 'CUENTA' "
            + "FROM Vulnerabilidad v, Vulnerabilidad_Software x, Software s "
            + "WHERE v.idVulnerabilidad = x.idVulnerabilidad AND s.idSoftware = x.idSoftware "
            + "AND v.fecha_publicacion < GETDATE() GROUP BY s.fabricante ";

    /**
     *
     */
    public static final String InsertarGrupoVulnerabilidad = "INSERT INTO Grupo_Vulnerabilidad "
            + "(idGrupo, idVulnerabilidad, afecta, resuelto, fechaSolucion, avance) "
            + "VALUES(?, ?, ?, ?, ?, ?);";
    /*
     + "UNION ALL " 
     + "SELECT 'Total', COUNT('CUENTA') " 
     + "FROM Vulnerabilidad v, Vulnerabilidad_Software x, Software s " 
     + "WHERE v.idVulnerabilidad = x.idVulnerabilidad AND s.idSoftware = x.idSoftware " 
     + " AND v.fecha_publicacion < GETDATE();";
     */

    /**
     * Constructor
     */
    public VulnerabilityDAO() {
    }

    /**
     * Método para obtener la conexión a BD
     *
     * @return objeto de tipo Conexión que contiene la conexión a la BD
     */
    private static Connection getConnection() {
        Connection con = ConnectionFactory.getInstance().getConnection();
        return con;
    }

    /**
     * GETTER
     *
     * @return cantidad de vulnerabilidades recientes
     */
    public int obtenerCantidadRecientes() {
        return cantidadRecientes;
    }

    /**
     * GETTER
     *
     * @return cantidad del archivo de vulnerabilidades
     */
    public int obtenerCantidadArchivo() {
        return cantidadArchivo;
    }

    /**
     * Método que retorna la lista de vulnerabilidades recientes
     *
     * @return lista con todas las vulnerabildiades recientes
     */
    public List<CVE> obtenerListaRecientes() {
        prepararListaReciente();
        if (!listaRecientes.isEmpty()) {
            return listaRecientes;
        }
        return new ArrayList<CVE>();
    }

    /**
     * Método que retorna la lista de archivo de vulnerabilidades
     *
     * @return lista con todas las vulnerabildiades del archivo
     */
    public List<CVE> obtenerListaArchivo() {
        prepararArchivo();
        if (!listaArchivo.isEmpty()) {
            return listaArchivo;
        }
        return new ArrayList<CVE>();
    }

    /**
     * Método que se encarga de obtener la url de una fuente
     *
     * @param id llave de la fuente a buscar
     * @return url de la fuente seleccionada
     */
    private String obtenerURL(int id) {
        String url = "";
        try {
            //Obtener conexión y preparar statement
            connection = getConnection();
            pstmt = connection.prepareStatement(getURLQuery);
            pstmt.setInt(1, id);
            ResultSet rs = pstmt.executeQuery();
            //Iterar el resultado
            while (rs.next()) {
                url = rs.getString(1);
            }
            LOG.log(Level.INFO, "La url obtenida es: {0}", url);
        } catch (SQLException ex) {
            LOG.log(Level.SEVERE, "ocurrio un error al obtener la URL {0}: {1}", new Object[]{id, ex.getMessage()});
        }
        return url;
    }

    /**
     * Método que se encarga de obtener una lista de vulnerabilidades recientes
     *
     * @param offset variable de inicio
     * @param noregs cantidad de registros
     * @return lista con la cantidad de vulnerabilidades indicada
     */
    public List<CVE> obtenerDeRecientes(int offset, int noregs) {
        //Inicializar la lista de vulnerabilidades reciente
        prepararListaReciente();
        //Instanciar una lista y un objeto de vulnerabilidad
        List<CVE> temp = new ArrayList<CVE>();
        CVE nCVE;
        //Iterar la lista de vulnerabildades para retornar las solicitadas
        for (int i = offset; i < offset + noregs; i++) {
            if (i >= this.cantidadRecientes) {
                break;
            }
            nCVE = listaRecientes.get(i);
            temp.add(nCVE);
        }
        return temp;
    }

    private static String sqlReadFileContent = "SELECT contenido_xml FROM FuenteApp WHERE idFuenteApp = ?;";

    /**
     * Método que se encarga de inicializar la lista de vulnerabilidades
     */
    private void prepararListaReciente() {
        try {
            //Inicializar el parser
            mCVEParser = new VulnerabilityParser();
            //Obtener URL de DB
            String dburl = obtenerURL(1);
            //URL url = new URL("http://nvd.nist.gov/download/nvdcve-recent.xml");
            URL url = new URL(dburl);
            /**
             * En caso de no contar con acceso a internet realizarlo de manera
             * local
             *
             * listaCVE =
             * mCVEParser.getListCVE(getClass().getResourceAsStream("/resources/nvdcve-recent.xml"));
             */
            listaRecientes = mCVEParser.getListCVE(url.openStream());
            //TEST
            //>connection = getConnection();
            //>pstmt = connection.prepareStatement(sqlReadFileContent);
            //>LOG.log(Level.INFO, "VulnerabilityDAO#prepararListaReciente() - Obteniendo contenido de BD . . .");
            //>pstmt.setInt(1, 1); //TODO: Hacer método get Index
            //>byte [] contenidoxml = null;
            //>rs = pstmt.executeQuery();
            //>while (rs.next()) {
            //>contenidoxml = rs.getBytes("contenido_xml");
            //>}
            //>rs.close();
            //>InputStream is = new ByteArrayInputStream(contenidoxml);
            //listaRecientes = mCVEParser.getListCVE(is);
            LOG.log(Level.INFO, "VulnerabilityDAO#prepararListaReciente() - Se encontraron: {0} vulnerabilidades.", listaRecientes.size());
            //TEST
            if (listaRecientes.isEmpty()) {
                listaRecientes = new ArrayList<CVE>();
            }
            //Ordenar la lista de vulnerabilidades
            Collections.sort(listaRecientes);
            this.cantidadRecientes = listaRecientes.size();
            //>} catch (SQLException ex) {
            //>LOG.log(Level.INFO, "VulnerabilityDAO#prepararListaReciente() - Ocurrio una excepci\u00f3n SQL: {0}", ex.getMessage());
        } catch (MalformedURLException ex) {
            Logger.getLogger(VulnerabilityDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(VulnerabilityDAO.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#prepararListaReciente() - Ocurrio una excepci\u00f3n al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }

    }

    /**
     * Método que se encarga de retornar el archivo de vulnerabilidades
     *
     * @param offset registro de inicio
     * @param noOfRecords cantidad de registros
     * @return lista con la cantidad de vulnerabilidades solicitada
     */
    public List<CVE> obtenerDeArchivo(int offset, int noOfRecords) {
        //Inicializar la lista de archivo
        prepararArchivo();
        //Instaciar una lista de vulnerabilidades y un objeto de tipo CVE
        List<CVE> temp = new ArrayList<CVE>();
        CVE nCVE;
        for (int i = offset; i < offset + noOfRecords; i++) {
            if (i >= this.cantidadArchivo) {
                break;
            }
            //Agregar el elemtno a la lista
            nCVE = listaArchivo.get(i);
            temp.add(nCVE);
        }
        if (temp.isEmpty()) {
            return new ArrayList<CVE>();
        }
        return temp;
    }

    //Evitar que traiga las recientes y el diccionario CPE
    private static final String sqlReadAllContent = "SELECT idFuenteApp, contenido_xml FROM FuenteApp WHERE idFuenteApp != 1 AND idFuenteApp != 5;";

    /**
     * Método que se encarga de inicializar la lista de archivo
     */
    private void prepararArchivo() {
        try {
            //Inicializar el parser
            mCVEParser = new VulnerabilityParser();
            connection = getConnection();
            pstmt = connection.prepareStatement(sqlReadAllContent);
            //>LOG.log(Level.INFO, "VulnerabilityDAO#preparaArchivo() - Obteniendo contenido de BD");
            byte[] contenidoxml = null;
            rs = pstmt.executeQuery();
            listaArchivo = new ArrayList<CVE>();
            List<CVE> listatemporal = new ArrayList<CVE>();
            while (rs.next()) {
                contenidoxml = rs.getBytes("contenido_xml");
                if (contenidoxml != null) {
                    InputStream is = new ByteArrayInputStream(contenidoxml);
                    listatemporal = mCVEParser.getListCVE(is);
                    if (!listatemporal.isEmpty()) {
                        listaArchivo.addAll(listatemporal);
                    }
                } else {
                    throw new Exception("El flujo de bytes de la fuente es nulo o el contenido es incorrecto");
                }
            }
            rs.close();
            //Ordenar los elementos y establecer la cantidad de vulnerabilidades
            Set<CVE> diferentes = new LinkedHashSet<CVE>();
            Set<CVE> duplicados = new LinkedHashSet<CVE>();
            for (CVE cve : listaArchivo) {
                if (diferentes.contains(cve)) {
                    duplicados.add(cve);
                } else {
                    diferentes.add(cve);
                }
            }
            listaArchivo = new ArrayList<CVE>();
            listaArchivo.addAll(diferentes);
            Collections.sort(listaArchivo);
            LOG.log(Level.INFO, "VulnerabilityDAO#preparaArchivo() - Se encontraron: {0} vulnerabilidades", listaArchivo.size());
            this.cantidadArchivo = listaArchivo.size();
        } catch (SQLException ex) {
            LOG.log(Level.INFO, "VulnerabilityDAO#preparaArchivo() - Ocurrio una excepci\u00f3n de SQL: {0}", ex.getMessage());
        } catch (Exception ex) {
            LOG.log(Level.SEVERE, "VulnerabilityDAO#prepararArchivo() - Ocurrio un problema al leer el contenido de la fuente: {0}", ex.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#preparaArchivo() - Ocurrio una excepci\u00f3n al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
    }

    /**
     * Método que se encarga de describir a detalle una vulnerabidad
     *
     * @param tipo el tipo de vulnerabilidad 1 para recientes 2 para archivo
     * @param name nombre de la vulnerabilidad
     * @return retorna un flujo para presentarlo en la vista
     */
    public String describirCVE(int tipo, String name) {
        //Instanciar un objeto de tipo CVE
        CVE temp = null;
        //Instanciar el buffer
        StringBuilder sb = new StringBuilder();
        //Codigo HTML
        sb.append("<table id=\"tableexport\" border=\"1\">");
        sb.append("<thead>");
        sb.append("<tr>");
        sb.append("<td colspan=\"2\" class=\"vulnHeader\">").append(name).append("</td>");
        sb.append("</tr>");
        sb.append("</thead>");
        //Buscar la vulnerabilidad en las listas a partir del parametro tipo
        if (tipo == 1) {
            for (CVE cve : listaRecientes) {
                if (cve.getName().toString().equals(name)) {
                    temp = cve;
                    break;
                }
            }
        } else if (tipo == 2) {
            for (CVE cve : listaArchivo) {
                if (cve.getName().toString().equals(name)) {
                    temp = cve;
                    break;
                }
            }
        }
        //Codigo HTML
        sb.append("<tbody>");
        DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
        sb.append("<tr>");
        sb.append("<td>").append("Fecha de Publicación:").append("</td>").append("<td id=\"pubdate\">").append(df.format(temp.getPublished())).append("</td>");
        sb.append("</tr>");
        sb.append("<tr>");
        sb.append("<td>").append("Fecha de Modificación:").append("</td>").append("<td id=\"moddate\">").append(df.format(temp.getModified())).append("</td>");
        sb.append("</tr>");
        sb.append("<tr>");
        sb.append("<td>Descripción:").append("</td>").append("<td id=\"desc\">").append(temp.getDescription()).append("</td>");
        sb.append("</tr>");
        sb.append("<tr>");
        //Traducción de la gravedad de la vulnerabilidad
        String severity = "";
        if (temp.getSeverity().equalsIgnoreCase("high")) {
            severity = "Alta";
        } else if (temp.getSeverity().equalsIgnoreCase("medium")) {
            severity = "Media";
        } else if (temp.getSeverity().equalsIgnoreCase("low")) {
            severity = "Baja";
        } else {
            severity = "ND";
        }
        //Codigo HTML
        sb.append("<td>").append("Gravedad:").append("</td>").append("<td id=\"criticidad\">").append(severity).append("</td>");
        sb.append("</tr>");
        sb.append("<tr>");
        sb.append("<td>").append("(CVSS) Calificación:").append("</td>").append("<td id=\"cvsscore\">").append(temp.getCVSS().score).append("</td>");
        sb.append("</tr>");
        sb.append("<tr>");
        sb.append("<td>").append("(CVSS) Vector de Ataque:").append("</td>").append("<td>");
        //Descripción del Vector de la vulnerabilidad
        if (!temp.getCVSS().vector.toString().equals("") && !temp.getCVSS().vector.equals("ND")) {
            sb.append(describirVector(temp.getCVSS().vector));
        } else {
            sb.append("<p id=\"cvssvector\">Vector No Disponible</p>");
        }
        sb.append("</td>");
        sb.append("</tr>");
        sb.append("<tr>");
        //Lista de referencias
        sb.append("<td>").append("Referencias:").append("</td>").append("<td id='refs'>");
        if (temp.getReferences().size() > 0) {
            sb.append("<table style='border: none;'>");
            for (int i = 0; i < temp.getReferences().size(); i++) {
                sb.append("<tr>");
                sb.append("<td>").append(temp.getReferences().get(i).getSource()).append("</td>");
                sb.append("<td>").append(temp.getReferences().get(i).getUrl()).append("</td>");
                sb.append("</tr>");
            }
            sb.append("</table>");
        } else {
            sb.append("ND");
        }
        sb.append("</td>");
        sb.append("</tr>");
        sb.append("<input id='hiddenRefs' type='hidden' value='").append(parseRefs(temp.getReferences())).append("' />");
        sb.append("<tr>");
        sb.append("<td>").append("Software Vulnerable:").append("</td>");
        sb.append("<td>");
        //Lista de Software Vulnerable
        if (temp.getVuln_soft().size() > 0) {
            sb.append("<table style='border: none;'>");
            sb.append("<thead>");
            sb.append("<tr>");
            sb.append("<td>").append("Proveedor").append("</td>");
            sb.append("<td>").append("Producto").append("</td>");
            sb.append("<td>").append("Versión(es)").append("</td>");
            sb.append("</tr>");
            sb.append("</thead>");
            for (int i = 0; i < temp.getVuln_soft().size(); i++) {
                sb.append("<tr>");
                sb.append("<td>").append(temp.getVuln_soft().get(i).getVendor().toUpperCase()).append("</td>");
                sb.append("<td>").append(temp.getVuln_soft().get(i).getName()).append("</td>");
                sb.append("<td>").append(temp.getVuln_soft().get(i).getVersion().toString()).append("</td>");
                sb.append("</tr>");
            }
            sb.append("</table>");
        } else {
            sb.append("ND");
        }
        //Codigo HTML
        sb.append("</td>");
        sb.append("</tr>");
        sb.append("<input id='hiddenSW' type='hidden' value='");
        if (!(temp.getVuln_soft().isEmpty())) {
            sb.append(parseSW(temp.getVuln_soft()));
        } else {
            sb.append("Lista temporalmente vacía.");
        }
        sb.append("' />");
        //Botón de Descarga
        sb.append("<tr>");
        sb.append("<td>").append("Descargar").append("</td>");
        sb.append("<td>");
        sb.append("<button onclick=\"javascript:toPDF(");
        sb.append("\'").append(temp.getName()).append("\'");
        sb.append(")\">");
        sb.append("Versión PDF</button>");
        sb.append("</td>");
        sb.append("</tr>");
        sb.append("</tbody>");
        sb.append("</table>");
        return sb.toString();
    }

    /**
     * Método que se encarga de realizar la descripción de un vector de ataque
     * Un vector de ataque puede ser de la forma:
     * (AV:[L,A,N]/AC:[H,M,L]/Au:[N,S,M]/C:[N,P,C]/I:[N,P,C]/A:[N,P,C])
     *
     * @param vector la representación del vector como cadena
     * @return cadena con la descripción del vector
     */
    public String describirVector(String vector) {
        //Partir la cadena original por los caracteres (:/)
        //System.out.println("VulnerabilityDAO#describirVector - Vector recibido: " + vector);
        StringTokenizer tokens = new StringTokenizer(vector, "(:/)");
        StringBuilder sb = new StringBuilder();
        int nDatos = tokens.countTokens();
        String[] vec = new String[nDatos];
        int i = 0;
        while (tokens.hasMoreTokens()) {
            vec[i] = tokens.nextToken().toString();
            i++;
        }
        vec[0] = "Vector de Acceso: ";
        if (vec[1].equalsIgnoreCase("L")) {
            vec[1] = "Acceso Local";
        } else if (vec[1].equalsIgnoreCase("A")) {
            vec[1] = "Red Adyacente";
        } else if (vec[1].equalsIgnoreCase("N")) {
            vec[1] = "Red";
        }
        vec[2] = "Complejidad de Acceso: ";
        if (vec[3].equalsIgnoreCase("H")) {
            vec[3] = "Alta";
        } else if (vec[3].equalsIgnoreCase("M")) {
            vec[3] = "Media";
        } else if (vec[3].equalsIgnoreCase("L")) {
            vec[3] = "Baja";
        }
        vec[4] = "Autenticación: ";
        if (vec[5].equalsIgnoreCase("N")) {
            vec[5] = "No requerida";
        } else if (vec[5].equalsIgnoreCase("S")) {
            vec[5] = "Requiere una instancia";
        } else if (vec[5].equalsIgnoreCase("M")) {
            vec[5] = "Requiere múltiples instancias";
        }
        vec[6] = "Impacto en Confidencialidad: ";
        if (vec[7].equalsIgnoreCase("N")) {
            vec[7] = "No tiene";
        } else if (vec[7].equalsIgnoreCase("P")) {
            vec[7] = "Parcial";
        } else if (vec[7].equalsIgnoreCase("C")) {
            vec[7] = "Completo";
        }
        vec[8] = "Impacto en integridad: ";
        //N = None, P = Partial, C = Complete
        if (vec[9].equalsIgnoreCase("N")) {
            vec[9] = "No tiene";
        } else if (vec[9].equalsIgnoreCase("P")) {
            vec[9] = "Parcial";
        } else if (vec[9].equalsIgnoreCase("C")) {
            vec[9] = "Completo";
        }
        vec[10] = "Impacto en Disponibilidad: ";
        // N = None, P = Partial, C = Complete
        if (vec[11].equalsIgnoreCase("N")) {
            vec[11] = "No tiene";
        } else if (vec[11].equalsIgnoreCase("P")) {
            vec[11] = "Parcial";
        } else if (vec[11].equalsIgnoreCase("C")) {
            vec[11] = "Completo";
        }
        sb.append("<table style='border: none;font-size:9pt;'>");
        sb.append("<tr>")
                .append("<td>Vector Original</td>")
                .append("<td id='cvssvector'>")
                .append(vector)
                .append("</td>")
                .append("</tr>");
        for (int j = 0; j < vec.length; j++) {
            sb.append("<tr>");
            sb.append("<td>")
                    .append(vec[j])
                    .append("</td>");
            j++;
            sb.append("<td>")
                    .append(vec[j])
                    .append("</td>");
            sb.append("</tr>");
        }
        sb.append("</table>");
        return sb.toString();
    }

    /**
     * Método que se encarga de representar como cadena los objetos de tipo
     * Software de la lista de software vulnerable
     *
     * @param vuln_soft Lista de software vulnerable
     * @return buffer con la representación de un objeto software
     */
    private Object parseSW(List<VulnSoftware> vuln_soft) {
        StringBuilder sb = new StringBuilder();
        for (VulnSoftware sw : vuln_soft) {
            sb.append("Proveedor: ");
            sb.append(sw.getVendor().toUpperCase());
            sb.append(" \nProducto: ");
            sb.append(sw.getName());
            sb.append(" \nVersión(es): ");
            sb.append(sw.getVersion());
            sb.append("/");
        }
        return sb.toString();
    }

    /**
     * Método que se encarga de representar como cadena los objetos de tipo
     * referencia de la lista de referencias
     *
     * @param references lista de referencias
     * @return buffer con la representación de la referencia
     */
    private Object parseRefs(List<CVEReference> references) {
        StringBuilder sb = new StringBuilder();
        for (CVEReference ref : references) {
            sb.append("Source:\t\t");
            sb.append(ref.getSource());
            sb.append("\nURL:\t\t");
            sb.append(ref.getUrl());
            sb.append("¿");
        }
        return sb.toString();
    }

    //Operaciones CRUD
    /**
     * Método que se encarga de registrar una vulnerabilidad en la BD
     *
     * @param vuln objeto de tipo vulnerabilidad a guardar
     * @return bandera con el resultado de la operación
     */
    public boolean crearVulnerabilidad(Vulnerabilidad vuln) {
        boolean res = false;
        try {
            //Obtener conexión y preparar el statement
            connection = getConnection();
            pstmt = connection.prepareStatement(sqlInsertarVulnerabilidad);
            pstmt.setString(1, vuln.getIdVulnerabilidad());
            pstmt.setString(2, vuln.getSeveridad());
            pstmt.setDate(3, new java.sql.Date(vuln.getFechaPublicacion().getTime()));
            pstmt.setDate(4, new java.sql.Date(vuln.getFechaModificacion().getTime()));
            pstmt.setString(5, vuln.getDescripcion());
            pstmt.setDouble(6, vuln.getCalificacionCVSS());
            pstmt.setString(7, vuln.getVectorCVSS());
            //Ejecutar inserción
            pstmt.executeUpdate();
            res = true;
        } catch (SQLException e) {
            LOG.log(Level.INFO, "Ocurrio una excepci\u00f3n de SQL: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "Ocurrio una excepci\u00f3n al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return res;
    }

    /**
     * Método para crear una vulnerabilidad a partir de un objeto de tipo
     * resultado
     *
     * @param resultado objeto de tipo resultado para extraer la vulnerabilidad,
     * las referencias y el software
     * @return bandera con el resultado de la ejecución, true si se ejecuta,
     * false si ocurre un error
     * @throws java.sql.SQLException
     */
    public boolean crearVulnerabilidad(Result resultado) throws SQLException {
        boolean flag = false;
        GrupoVulnerabilidadDAO gvdao = new GrupoVulnerabilidadDAO();
        try {
            CVE cve = resultado.getVulnerabilidad();
            connection = getConnection();
            connection.setAutoCommit(false);
            pstmt = connection.prepareStatement(sqlInsertarVulnerabilidad);
            pstmt.setString(1, cve.getName());
            String sev = cve.getSeverity();
            if (sev.equalsIgnoreCase("high")) {
                sev = "Alta";
            } else if (sev.equalsIgnoreCase("medium")) {
                sev = "Media";
            } else if (sev.equalsIgnoreCase("low")) {
                sev = "Baja";
            } else {
                sev = "ND";
            }
            pstmt.setString(2, sev);
            pstmt.setDate(3, new java.sql.Date(cve.getPublished().getTime()));
            pstmt.setDate(4, new java.sql.Date(cve.getModified().getTime()));
            pstmt.setString(5, cve.getDescription());
            pstmt.setDouble(6, Double.parseDouble(cve.getCVSS().getScore()));
            pstmt.setString(7, cve.getCVSS().getVector());
            int res = pstmt.executeUpdate();
            LOG.log(Level.INFO, "VulnerabilityDAO#crearVulnerabilidad() - Vulnerabilidad creada con resultado: {0}", res);
            for (CVEReference referenciacve : cve.getReferences()) {
                pstmt = connection.prepareStatement(sqlInsertVulnReference);
                pstmt.setString(1, cve.getName());
                pstmt.setString(2, referenciacve.getSource());
                pstmt.setString(3, referenciacve.getUrl());
                res = pstmt.executeUpdate();
                //LOG.log(Level.INFO, "VulnerabilityDAO#crearVulnerabilidad() - Referencia de Vulnerabilidad creada con resultado: {0}", res);
            }
            SoftwareDAO swdao = new SoftwareDAO();
            for (Software swvuln : resultado.getSwList()) {
                pstmt = connection.prepareStatement(sqlInsertVulnSW);
                pstmt.setString(1, cve.getName());
                pstmt.setInt(2, swvuln.getIdSoftware());
                res = pstmt.executeUpdate();
                //LOG.log(Level.INFO, "VulnerabilityDAO#crearVulnerabilidad() - Software de vulnerabilidad agregado con resultado: {0}", res);
            }
            //Insertar la vulnerabilidad en la relación Grupo_Vulnerabilidad
            //gvdao.registrarVulnerabilidadesEnGrupo(res, resultado.getVulnerabilidad().getName());
            List<String> grupos = resultado.getGruposList();
            GruposDAO gdao = new GruposDAO();
            for (String grupo : grupos) {
                Grupo g = gdao.obtenerGrupoPorNombre(grupo);
                pstmt = connection.prepareStatement(InsertarGrupoVulnerabilidad);
                pstmt.setInt(1, g.getIdGrupo());
                pstmt.setString(2, cve.getName());
                pstmt.setInt(3, 0);
                pstmt.setInt(4, 0);
                pstmt.setDate(5, null);
                pstmt.setInt(6, 0);
                int guardado = pstmt.executeUpdate();
                LOG.log(Level.INFO, "VulnerabilityDAO#crearVulnerabilidad() - Grupo_Vulnerabilidad agregado ({0}, {1})", new Object[]{g.getIdGrupo(), cve.getName()});
                //boolean temp = gvdao.registrarVulnerabilidadesEnGrupo(g.getIdGrupo(), resultado.getVulnerabilidad().getName());
                //LOG.log(Level.INFO, "VulnerabilityDAO#crearVulnerabilidad() - Resultado: {0}", temp);
            }
            connection.commit();
            flag = true;
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#crearVulnerabilidad() - Ocurrio un error al preparar la sentencia SQL: {0}", e.getMessage());
            connection.rollback();
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#crearVulnerabilidad() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return flag;
    }

    /**
     * Método que se encarga de realizar la edición de una vulnerabiliddad
     *
     * @param vuln vulnerabilidad a editar
     * @return bandera con el resultado de la ejecución de la vulnerabilidad
     */
    public boolean editarVulnerabilidad(Vulnerabilidad vuln) {
        boolean res = false;
        try {
            //obtener conexión y preparar el statement
            connection = getConnection();
            pstmt = connection.prepareStatement(sqlActualizarVulnerabilidad);
            pstmt.setString(1, vuln.getSeveridad());
            pstmt.setDate(2, new java.sql.Date(vuln.getFechaPublicacion().getTime()));
            pstmt.setDate(3, new java.sql.Date(vuln.getFechaModificacion().getTime()));
            pstmt.setString(4, vuln.getDescripcion());
            pstmt.setDouble(5, vuln.getCalificacionCVSS());
            pstmt.setString(6, vuln.getVectorCVSS());
            pstmt.setString(7, vuln.getIdVulnerabilidad());
            //Realizar la edición
            pstmt.executeUpdate();
            res = true;
        } catch (SQLException e) {
            LOG.log(Level.INFO, "Ocurrio una excepci\u00f3n de SQL: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "Ocurrio una excepci\u00f3n al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return res;
    }

    /**
     * Método que se encarga de eliminar una vulnerabilidad a partir de su id
     *
     * @param idVulnerabilidad nombre de la vulnerabilidad
     * @return bandera con el resultado de la ejecución
     */
    public boolean eliminarVulnerabilidad(String idVulnerabilidad) {
        boolean res = false;
        try {
            //Obtener conexión y preparar el statement
            connection = getConnection();
            pstmt = connection.prepareStatement(sqlEliminarVulnerabilidad);
            pstmt.setString(1, idVulnerabilidad);
            //Ejecutar la eliminación
            pstmt.executeUpdate();
            res = true;
        } catch (SQLException e) {
            LOG.log(Level.INFO, "Ocurrio una excepci\u00f3n de SQL: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "Ocurrio una excepci\u00f3n al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return res;
    }

    /**
     * Método que implementa una función 'LIKE' de SQL para obtener
     * coincidencias
     *
     * @param term referencia de la vulnerabilidad
     * @return lista de vulnerabilidades que cumplen el criterio
     */
    public List<CVE> retrieveCVEsLike(String term) {
        List<CVE> likes = new ArrayList<CVE>();
        for (CVE cve : listaArchivo) {
            //Si el nombre de la vulnerabilidad se parece al de la clave agregarla a la lista
            String cvename = cve.getName().toLowerCase();
            String key = term.toLowerCase();
            if (cvename.contains(key) || cvename.endsWith(key)) {
                likes.add(cve);
            }
        }
        return likes;
    }

    /**
     * Método que se encarga de buscar una vulnerabilidad
     *
     * @param key clave de la busqueda
     * @return lista de vulnerabilidades que cumplen el criterio
     */
    public List<CVE> searchCVE(String key) {
        //Instanciar una lista para el resultado y 2 conjuntos para eliminar duplicados
        List<CVE> found = new ArrayList<CVE>();
        Set<CVE> diferentes = new LinkedHashSet<CVE>();
        Set<CVE> duplicados = new LinkedHashSet<CVE>();
        prepararArchivo();
        //Buscar la coincidencia
        for (CVE cve : listaArchivo) {
            if (cve.getName().equalsIgnoreCase(key) || cve.getName().endsWith(key) || cve.getName().toLowerCase().contains(key)) {
                LOG.log(Level.INFO, "A\u00f1adiendo a resultados: {0}", cve.getName());
                found.add(cve);
            }
        }
        //En caso de existir duplicados eliminarlos
        for (CVE cve : found) {
            if (diferentes.contains(cve)) {
                duplicados.add(cve);
            } else {
                diferentes.add(cve);
            }
        }
        //Reiniciar la lista de vulnerabilidades y agregarle las diferentes
        found = new ArrayList<CVE>();
        found.addAll(diferentes);
        if (!found.isEmpty()) {
            return found;
        }
        return new ArrayList<CVE>();
    }

    /**
     * Método que se encarga de validar la existencia de una vulnerabildiad en
     * la base de datos, a partir del nombre de la vulnerabilidad returna 0 para
     * no existente y 1 para existente
     *
     * @param name nombre de la vulnerabilidad
     * @return entero con el valor 0 para no encontrado 1 para encontrado
     */
    public int comprobarExistenciaVulnerabilidad(String name) {
        int res = 0;
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(sqlBuscarExistenciaVulnerabilidad);
            pstmt.setString(1, "%" + name + "%");
            rs = pstmt.executeQuery();
            String nombre = "";
            while (rs.next()) {
                nombre = rs.getString("idVulnerabilidad");
            }
            if (!nombre.equals("") && !nombre.isEmpty()) {
                res = 1;
            }
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#comprobarExistenciaVulnerabilidad() - Ocurrio un error al preparar la sentencia: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#comprobarExistenciaVulnerabilidad() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return res;
    }

    /**
     * Método que se encarga de obtener las vulnerabilidades recientes para
     * mostrarlas en el dashboard
     *
     * @return lista de vulnerabilidades registradas en la base de datos
     */
    public List<Vulnerabilidad> obtenerVulnerabilidadesRecientes() {
        List<Vulnerabilidad> recientes = null;
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(sqlObtenerVulnerabilidadesRecientes);
            rs = pstmt.executeQuery();
            Vulnerabilidad temp;
            recientes = new ArrayList<Vulnerabilidad>();
            while (rs.next()) {
                temp = new Vulnerabilidad();
                temp.setIdVulnerabilidad(rs.getString("idVulnerabilidad"));
                temp.setSeveridad(rs.getString("severidad"));
                temp.setFechaPublicacion(rs.getDate("fecha_publicacion"));
                temp.setFechaModificacion(rs.getDate("fecha_modificacion"));
                temp.setDescripcion(rs.getString("descripcion"));
                temp.setCalificacionCVSS(rs.getDouble("calificacion_cvss"));
                temp.setVectorCVSS(rs.getString("vector_cvss"));
                pstmt = connection.prepareStatement(sqlObtenerSoftwareDeVulnerabilidad);
                pstmt.setString(1, temp.getIdVulnerabilidad());
                ResultSet rs2 = pstmt.executeQuery();
                List<Software> listaSoftware = new ArrayList<Software>();
                while (rs2.next()) {
                    Software stemp = new Software();
                    stemp.setIdSoftware(rs2.getInt("idSoftware"));
                    stemp.setFabricante(rs2.getString("fabricante"));
                    stemp.setNombre(rs2.getString("nombre"));
                    stemp.setVersion(rs2.getString("version"));
                    listaSoftware.add(stemp);
                }
                rs2.close();
                temp.setListaSoftware(listaSoftware);
                recientes.add(temp);
            }
            rs.close();
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#obtenerVulnerabilidadesRecientes() - Ocurrio un error al preparar la sentencia: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#obtenerVulnerabilidadesRecientes() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return recientes;
    }

    /**
     * Método que se encarga de obtener una lista de grupos en donde se
     * encuentra el software afectado
     *
     * @param afectado lista de software afectado
     * @return lista de grupos en donde se encuentra presente el software
     * afectado
     */
    public List<Grupo> obtenerGrupos(List<Software> afectado) {
        List<Grupo> encontrados = null;
        try {
            connection = getConnection();
            encontrados = new ArrayList<Grupo>();
            for (Software software : afectado) {
                pstmt = connection.prepareStatement(sqlObtenerGruposConSoftware);
                pstmt.setInt(1, software.getIdSoftware());
                rs = pstmt.executeQuery();
                while (rs.next()) {
                    Grupo temp = new Grupo();
                    temp.setIdGrupo(rs.getInt("idGrupo"));
                    temp.setNombre(rs.getString("nombre"));
                    temp.setCategoria(rs.getString("categoria"));
                    encontrados.add(temp);
                }
                rs.close();
            }
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#obtenerGrupos() - Ocurrio un error al preparar la sentencia: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#obtenerGrupos() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return encontrados;
    }

    /**
     * Método que se encarga de obtener la información de una vulnerabilidad a
     * partir de su nombre
     *
     * @param nombre identificador de la vulnerabilidad del tipo CVE-201X-XXXX
     * @return Objeto de tipo vulnerabilidad correspondiente al nombre ingresado
     */
    public Vulnerabilidad obtenerVulnerabilidadPorNombre(String nombre) {
        Vulnerabilidad v = null;
        try {
            connection = getConnection();
            v = new Vulnerabilidad();
            pstmt = connection.prepareStatement(sqlObtenerVulnerabilidadPorNombre);
            pstmt.setString(1, nombre);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                v.setIdVulnerabilidad(rs.getString("idVulnerabilidad"));
                v.setSeveridad(rs.getString("severidad"));
                v.setFechaPublicacion(rs.getDate("fecha_publicacion"));
                v.setFechaModificacion(rs.getDate("fecha_modificacion"));
                v.setDescripcion(rs.getString("descripcion"));
                v.setCalificacionCVSS(rs.getDouble("calificacion_cvss"));
                v.setVectorCVSS(rs.getString("vector_cvss"));
            }
            rs.close();
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#obtenerVulnerabilidadPorNombre() - Ocurrio un error al preparar la sentencia: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#obtenerVulnerabilidadPorNombre() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return v;
    }

    /**
     * Método que se encarga de obtener la lista de referencias de una
     * vulnerabilidad
     *
     * @param nombre identificador de la vulnerabilidad a buscar
     * @return lista con las referencias de la vulnerabilidad
     */
    public List<VulnerabilidadReferencia> obtenerReferencias(String nombre) {
        List<VulnerabilidadReferencia> referencias = null;
        try {
            connection = getConnection();
            referencias = new ArrayList<VulnerabilidadReferencia>();
            pstmt = connection.prepareStatement(sqlObtenerReferenciasPorNombre);
            pstmt.setString(1, nombre);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                VulnerabilidadReferencia temp = new VulnerabilidadReferencia();
                temp.setIdVulnerabilidad(nombre);
                temp.setIdReferencia(rs.getInt("idReferencia"));
                temp.setFuente(rs.getString("fuente"));
                temp.setUrl(rs.getString("url"));
                referencias.add(temp);
            }
            rs.close();
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#obtenerReferencias() - Ocurrio un error al preparar la sentencia: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#obtenerReferencias() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return referencias;
    }

    /**
     * Método que se encarga de obtener una lista de software vulnerable
     * correspondiente a una vulnerabilidad
     *
     * @param nombre nombre de la vulnerabilidad
     * @return lista de software afectado a partir del nombre de la
     * vulnerabilidad
     */
    public List<Software> obtenerSoftwareVulnerable(String nombre) {
        List<Software> sws = null;
        try {
            connection = getConnection();
            sws = new ArrayList<Software>();
            pstmt = connection.prepareStatement(sqlObtenerSoftwareVulnerablePorNombre);
            pstmt.setString(1, nombre);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                Software nuevo = new Software();
                nuevo.setIdSoftware(rs.getInt("idSoftware"));
                nuevo.setFabricante(rs.getString("fabricante"));
                nuevo.setNombre(rs.getString("nombre"));
                nuevo.setVersion(rs.getString("version"));
                nuevo.setTipo(rs.getInt("tipo"));
                nuevo.setEndoflife(rs.getInt("end_of_life"));
                nuevo.setUAResponsable("nd");
                nuevo.setAnalistaResponsable("nd");
                sws.add(nuevo);
            }
            rs.close();
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#obtenerSoftwareVulnerable() - Ocurrio un error al preparar la sentencia: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#obtenerSoftwareVulnerable() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return sws;
    }

    /**
     * Método que se encarga de obtener los grupos que son afectados por una
     * vulnerabilidad
     *
     * @param nombre identificador de la vulnerabilidad
     * @return lista con los grupos donde se encuentra presente la
     * vulnerabilidad
     */
    public List<Grupo> obtenerGruposPorVulnerabilidad(String nombre) {
        List<Grupo> grupos = null;
        try {
            connection = getConnection();
            grupos = new ArrayList<Grupo>();
            pstmt = connection.prepareStatement(sqlObtenerGruposPorVulnerabilidad);
            pstmt.setString(1, nombre);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                Grupo g = new Grupo();
                g.setIdGrupo(rs.getInt("idGrupo"));
                g.setNombre(rs.getString("nombre"));
                g.setCategoria(rs.getString("categoria"));
                grupos.add(g);
            }
            rs.close();
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#obtenerGruposPorVulnerabilidad() - Ocurrio un error al preparar la sentencia: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#obtenerGruposPorVulnerabilidad() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return grupos;
    }

    /**
     * Método que se encarga de obtener una relación que indica el numero de
     * vulnerabilidades que estan relacionadas con algun fabricante
     *
     * @return Mapa con los valores en par Fabricante-Cuenta
     */
    public HashMap<String, Integer> obtenerEstadisticasFabricantes() {
        HashMap<String, Integer> datos = new HashMap<String, Integer>();
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(sqlObtenerVulnerabilidadesporFabricante);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                datos.put(rs.getString("fabricante"), rs.getInt("CUENTA"));
            }
            rs.close();
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#obtenerEstadisticasFabricantes() - Ocurrio un error al preparar la sentencia: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#obtenerEstadisticasFabricantes() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return datos;
    }

    /**
     * Método que se encarga de obtener una relación que indice la gravedad de
     * todas las vulnerabilidades registradas
     *
     * @return Mapa con los pares de valores Gravedad Cantidad
     */
    public HashMap<String, Integer> obtenerGravedadVulnerabilidades() {
        HashMap<String, Integer> datos = new HashMap<String, Integer>();
        try {
            connection = getConnection();
            pstmt = connection.prepareStatement(sqlObtenerGravedadVulnerabilidades);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                datos.put("altas", rs.getInt("ALTAS"));
                datos.put("medias", rs.getInt("MEDIAS"));
                datos.put("bajas", rs.getInt("BAJAS"));
            }
            rs.close();
        } catch (SQLException e) {
            LOG.log(Level.INFO, "VulnerabilityDAO#obtenerGravedadVulnerabilidades() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                LOG.log(Level.INFO, "VulnerabilityDAO#obtenerGravedadVulnerabilidades() - Ocurrio un error al cerrar la conexi\u00f3n: {0}", e.getMessage());
            }
        }
        return datos;
    }

    /**
     *
     * public List<CVE> retrieveAllCVEs(int offset, int noOfRecords) { String
     * query = "SELECT * FROM DB LIMIT " + offset + ", " + noOfRecords;
     * List<CVE> cvelist = new ArrayList<CVE>(); CVE ncve = null; try {
     * connection = getConnection(); stmt = connection.createStatement();
     * ResultSet rs = stmt.executeQuery(query); while (rs.next()) { ncve = new
     * CVE(rs.getString("name"));
     * ncve.setDescription(rs.getString("description")); //TODO: Agregar los
     * restantes cvelist.add(ncve); } rs.close(); rs = stmt.executeQuery("SELECT
     * FOUND_ROWS()"); if (rs.next()) { this.cantidadRecientes = rs.getInt(1); }
     * } catch (SQLException e) { LOG.log(Level.INFO, "Ocurrio una
     * excepci\u00f3n SQL: {0}", e.getMessage()); } finally { try { if (stmt !=
     * null) { stmt.close(); } if (connection != null) { connection.close(); } }
     * catch (SQLException e) { LOG.log(Level.INFO, "Ocurrio una excepci\u00f3n
     * SQL: {0}", e.getMessage()); } } return cvelist; }
     *
     * public List<CVE> retrieveAllCVEsFromFile() { mCVEParser = new
     * VulnerabilityParser(); //mCVEParser.setFiltro(""); List<CVE> cveList =
     * mCVEParser.getListCVE(getClass().getResourceAsStream("/resources/nvdcve-recent.xml"));
     * if (cveList.isEmpty()) { return new ArrayList<CVE>(); } return cveList; }
     *
     * private int testRows;
     *
     *
     * public int getTestRows() { return testRows; }
     *
     * public List<String> getNombres(int offset, int noregs) { List<String>
     * temp = new ArrayList<String>(); String name = ""; for (int i = offset; i
     * < offset + noregs; i++) { if (i >= this.testRows) { break; } name =
     * nombres.get(i); temp.add(name); } return temp; }
     */
    /**
     * VERSION ANTERIOR DEL METODO PREPARA ARCHIVO private void
     * prepararArchivo() { String root = readPath.getRoot().toString(); String
     * subdir = readPath.subpath(0, 2).toString(); //Inicializar el parser
     * mCVEParser = new VulnerabilityParser(); //archivoCVE =
     * mCVEParser.getListCVE(getClass().getResourceAsStream("/resources/nvdcve-2014.xml"));
     * //Intanciar una lista para 2013 y una para 2014 List<CVE> dosmiltrece =
     * new ArrayList<CVE>(); String readDir = root + subdir + File.separator +
     * "vulnerabilidades" + File.separator; //File file = new File(root + subdir
     * + File.separator + "vulnerabilidades" + File.separator +
     * "nvdcve-2013.xml"); File file = new File(readDir + "nvdcve-2013.xml");
     * try { //dosmiltrece =
     * mCVEParser.getListCVE(getClass().getResourceAsStream("/resources/nvdcve-2013.xml"));
     * dosmiltrece = mCVEParser.getListCVE(new FileInputStream(file)); } catch
     * (FileNotFoundException ex) { LOG.log(Level.SEVERE, "No se encontro el
     * archivo de 2013: {0}", ex.getMessage()); } file = null; file = new
     * File(readDir + "nvdcve-2014.xml"); List<CVE> dosmilcatorce = new
     * ArrayList<CVE>(); try { //dosmilcatorce =
     * mCVEParser.getListCVE(getClass().getResourceAsStream("/resources/nvdcve-2014.xml"));
     * dosmilcatorce = mCVEParser.getListCVE(new FileInputStream(file)); } catch
     * (FileNotFoundException ex) { LOG.log(Level.SEVERE, "No se encontro el
     * archivo de 2014: {0}", ex.getMessage()); } //Inicializar la lista de
     * archivo y agregar las 2 listas anteriores listaArchivo = new
     * ArrayList<CVE>(); listaArchivo.addAll(dosmiltrece);
     * listaArchivo.addAll(dosmilcatorce); //Instanciar 2 conjuntos para
     * eliminar los elementos duplicados Set<CVE> diferentes = new
     * LinkedHashSet<CVE>(); Set<CVE> duplicados = new LinkedHashSet<CVE>();
     * //Iterar todo el archivo, y buscar elementos repetidos for (CVE cve :
     * listaArchivo) { if (diferentes.contains(cve)) { duplicados.add(cve); }
     * else { diferentes.add(cve); } } //Reiniciar la lista de archivo y agregar
     * solo los elementos diferentes listaArchivo = new ArrayList<CVE>();
     * listaArchivo.addAll(diferentes); if (listaArchivo.isEmpty()) {
     * listaArchivo = new ArrayList<CVE>(); } //Ordenar los elementos y
     * establecer la cantiodad de vulnerabilidades
     * Collections.sort(listaArchivo); this.cantidadArchivo =
     * listaArchivo.size(); }
     */
}
